﻿using System;
using NDBGen.Descriptors;
using NDBGen.Descriptors.Columns.DataTypes;
using NDBGen.Descriptors.Columns.Tokens;
using NDBGen.Descriptors.Tables.Tokens;

namespace NDBGen.Plugins.DataAccess
{
    public class DataAccessGeneratorPluginData : PluginData<IColumnDataTypeCodeSnippetGenerator, IColumnTokenCodeSnippetGenerator, ITableTokenCodeSnippetGenerator>
    {
        internal DataAccessGeneratorPluginData(ParsedInput parsedInput) : base(parsedInput) { }
    }

    public static class DataAccessPluginDataExtensions
    {
        public static IColumnDataTypeCodeSnippetGenerator GetGeneratorForDescriptor(this IGenerator generator, IColumnDataTypeDescriptor descriptor)
        {
            Type generatorType;
            if (generator.PluginData.ColumnDataTypeGenerators.TryGetValue(descriptor.GetType(), out generatorType))
            {
                return ActivateGenerator<IColumnDataTypeCodeSnippetGenerator, IColumnDataTypeDescriptor>(generatorType, generator.PluginData, descriptor);
            }
            else return null;
        }

        public static IColumnTokenCodeSnippetGenerator GetGeneratorForDescriptor(this IGenerator generator, IColumnTokenDescriptor descriptor)
        {
            Type generatorType;
            if (generator.PluginData.ColumnTokenGenerators.TryGetValue(descriptor.GetType(), out generatorType))
            {
                return ActivateGenerator<IColumnTokenCodeSnippetGenerator, IColumnTokenDescriptor>(generatorType, generator.PluginData, descriptor);
            }
            else return null;
        }

        public static ITableTokenCodeSnippetGenerator GetGeneratorForDescriptor(this IGenerator generator, ITableTokenDescriptor descriptor)
        {
            Type generatorType;
            if (generator.PluginData.TableTokenGenerators.TryGetValue(descriptor.GetType(), out generatorType))
            {
                return ActivateGenerator<ITableTokenCodeSnippetGenerator, ITableTokenDescriptor>(generatorType, generator.PluginData, descriptor);
            }
            else return null;
        }

        private static TGenerator ActivateGenerator<TGenerator, TDescriptor>(Type generatorType, IPluginData pluginData, TDescriptor descriptor)
            where TGenerator : IGenerator<TDescriptor>
            where TDescriptor : IDescriptor
        {
            var generator = (TGenerator)Activator.CreateInstance(generatorType);
            generator.Init(pluginData, descriptor);

            return generator;
        }
    }
}